#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
导出管理器
用于处理样本数据的Excel和PDF导出功能
"""

import logging
import os
import zipfile
from datetime import datetime
from typing import List, Dict, Any, Optional
from pathlib import Path

try:
    import pandas as pd
    import openpyxl
    from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
    from openpyxl.utils.dataframe import dataframe_to_rows
    from openpyxl.worksheet.worksheet import Worksheet
    EXCEL_AVAILABLE = True
except ImportError:
    EXCEL_AVAILABLE = False
    logging.warning("Excel导出功能不可用，请安装 pandas 和 openpyxl")

try:
    from reportlab.lib.pagesizes import A4
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.units import inch, cm
    from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image
    from reportlab.lib import colors
    from reportlab.pdfgen import canvas
    from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont
    PDF_AVAILABLE = True
except ImportError:
    PDF_AVAILABLE = False
    logging.warning("PDF导出功能不可用，请安装 reportlab")

from src.models.models import Sample, SampleStatus

logger = logging.getLogger(__name__)

class ExportManager:
    """导出管理器"""
    
    def __init__(self):
        self.hospital_name = "小苏科技"
        self.hospital_address = ""
        self.hospital_contact = ""
        self._register_fonts()
    
    def _register_fonts(self):
        """注册字体，解决中文字体问题"""
        if not PDF_AVAILABLE:
            return
            
        try:
            # 尝试注册多种中文字体
            chinese_fonts = [
                ("SimSun", "C:/Windows/Fonts/simsun.ttc"),
                ("SimSun", "C:/Windows/Fonts/simsun.ttf"),
                ("SimHei", "C:/Windows/Fonts/simhei.ttf"),
                ("Microsoft YaHei", "C:/Windows/Fonts/msyh.ttf"),
                ("KaiTi", "C:/Windows/Fonts/simkai.ttf"),
                ("FangSong", "C:/Windows/Fonts/simfang.ttf"),
                ("SimSun", "C:/Windows/Fonts/simsun.ttc"),
                ("SimSun", "C:/Windows/Fonts/simsun.ttf"),
                ("SimHei", "C:/Windows/Fonts/simhei.ttf"),
                ("Microsoft YaHei", "C:/Windows/Fonts/msyh.ttf"),
                ("KaiTi", "C:/Windows/Fonts/simkai.ttf"),
                ("FangSong", "C:/Windows/Fonts/simfang.ttf")
            ]
            
            registered_fonts = []
            
            for font_name, font_path in chinese_fonts:
                if os.path.exists(font_path):
                    try:
                        pdfmetrics.registerFont(TTFont(font_name, font_path))
                        registered_fonts.append(font_name)
                        logger.info(f"成功注册字体: {font_name} ({font_path})")
                        # 如果成功注册了SimSun，就停止尝试
                        if font_name == "SimSun":
                            break
                    except Exception as e:
                        logger.warning(f"注册字体失败 {font_name} ({font_path}): {e}")
                        continue
            
            # 如果没有成功注册任何中文字体，尝试使用系统默认字体
            if not registered_fonts:
                logger.warning("无法注册任何中文字体，将使用默认字体")
                # 尝试注册reportlab内置的中文字体
                try:
                    from reportlab.pdfbase.cidfonts import UnicodeCIDFont
                    pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
                    logger.info("成功注册UnicodeCIDFont: STSong-Light")
                except Exception as e:
                    logger.warning(f"注册UnicodeCIDFont失败: {e}")
                
        except Exception as e:
            logger.warning(f"字体注册过程中出现错误: {e}")
    
    def _get_safe_font(self) -> str:
        """获取安全的字体名称"""
        if not PDF_AVAILABLE:
            return "Helvetica"
            
        # 检查已注册的字体
        registered_fonts = pdfmetrics.getRegisteredFontNames()
        
        # 优先使用SimSun
        if 'SimSun' in registered_fonts:
            return 'SimSun'
        
        # 回退到其他中文字体
        chinese_fonts = ['SimHei', 'Microsoft YaHei', 'KaiTi', 'FangSong', 'STSong-Light']
        for font in chinese_fonts:
            if font in registered_fonts:
                return font
        
        # 最后使用默认字体
        return "Helvetica"
    
    def set_hospital_info(self, name: str, address: str = "", contact: str = ""):
        """设置医院信息"""
        self.hospital_name = name
        self.hospital_address = address
        self.hospital_contact = contact
    
    def export_samples_to_excel(self, samples: List[Sample], file_path: str, 
                               include_all_data: bool = True) -> bool:
        """导出样本数据到Excel文件"""
        try:
            if not EXCEL_AVAILABLE:
                logger.error("Excel导出功能不可用，请安装 pandas 和 openpyxl")
                return False
            
            if not samples:
                logger.warning("没有样本数据可导出")
                return False
            
            # 创建工作簿
            wb = openpyxl.Workbook()
            ws = wb.active
            ws.title = "样本数据"
            
            # 设置标题
            self._add_excel_header(ws, len(samples))
            
            # 添加数据
            self._add_sample_data(ws, samples, include_all_data)
            
            # 设置列宽
            self._set_column_widths(ws, include_all_data)
            
            # 保存文件
            wb.save(file_path)
            logger.info(f"Excel文件导出成功: {file_path}")
            return True
            
        except Exception as e:
            logger.error(f"导出Excel文件失败: {e}")
            return False
    
    def export_samples_to_pdf_zip(self, samples: List[Sample], zip_file_path: str) -> bool:
        """批量导出样本数据到PDF文件，并打包成ZIP文件"""
        try:
            if not PDF_AVAILABLE:
                logger.error("PDF导出功能不可用，请安装 reportlab")
                return False
            
            if not samples:
                logger.warning("没有样本数据可导出")
                return False
            
            # 创建临时目录存放PDF文件
            temp_dir = Path(zip_file_path).parent / f"temp_pdf_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
            temp_dir.mkdir(exist_ok=True)
            
            pdf_files = []
            
            try:
                # 为每个样本生成PDF文件
                for i, sample in enumerate(samples):
                    # 生成PDF文件名：患者姓名+分析时间
                    patient_name = sample.sample_info.patient_name or "未知患者"
                    analysis_time = sample.receive_time.strftime("%Y%m%d_%H%M%S") if sample.receive_time else "未知时间"
                    
                    # 清理文件名中的非法字符
                    safe_patient_name = "".join(c for c in patient_name if c.isalnum() or c in (' ', '-', '_')).rstrip()
                    safe_patient_name = safe_patient_name.replace(' ', '_')
                    
                    pdf_filename = f"{safe_patient_name}_{analysis_time}.pdf"
                    pdf_path = temp_dir / pdf_filename
                    
                    # 生成单个PDF文件
                    if self._generate_sample_pdf(sample, str(pdf_path)):
                        pdf_files.append(pdf_path)
                        logger.info(f"生成PDF文件: {pdf_filename}")
                    else:
                        logger.warning(f"生成PDF文件失败: {pdf_filename}")
                
                # 创建ZIP文件
                with zipfile.ZipFile(zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                    for pdf_file in pdf_files:
                        zipf.write(pdf_file, pdf_file.name)
                
                logger.info(f"PDF批量导出成功，共{len(pdf_files)}个文件，打包到: {zip_file_path}")
                return True
                
            finally:
                # 清理临时文件
                try:
                    import shutil
                    shutil.rmtree(temp_dir)
                    logger.info(f"临时目录已清理: {temp_dir}")
                except Exception as e:
                    logger.warning(f"清理临时目录失败: {e}")
            
        except Exception as e:
            logger.error(f"批量导出PDF失败: {e}")
            return False
    
    def _generate_sample_pdf(self, sample: Sample, pdf_path: str) -> bool:
        """生成单个样本的PDF报告"""
        try:
            # 创建PDF文档
            doc = SimpleDocTemplate(
                pdf_path,
                pagesize=A4,
                rightMargin=1.5*cm,
                leftMargin=1.5*cm,
                topMargin=1.5*cm,
                bottomMargin=1.5*cm
            )
            
            # 获取样式
            styles = getSampleStyleSheet()
            
            # 创建内容列表
            story = []
            
            # 添加标题
            title_style = ParagraphStyle(
                'CustomTitle',
                parent=styles['Heading1'],
                fontSize=16,
                spaceAfter=20,
                alignment=TA_CENTER,
                textColor=colors.black,
                fontName=self._get_safe_font()
            )
            title = Paragraph("样本检测报告（编号："+sample.sample_info.sample_id+"）", title_style)
            story.append(title)
            
            # 创建头部信息表格（患者信息、样本信息、仪器信息）
            header_data = [
                # 第一行：患者姓名、样本位置、仪器型号
                ["患者姓名", sample.sample_info.patient_name or "未知患者", 
                 "样本位置", sample.sample_info.position or "",
                 "仪器型号", sample.machine_model or "未知"],
                # 第二行：患者年龄、样本类型、仪器编号
                ["患者年龄", str(sample.sample_info.patient_age) if sample.sample_info.patient_age else "0", 
                 "样本类型", sample.sample_info.sample_type_name or "",
                 "仪器编号", sample.machine_id or "未知"],
                # 第三行：患者性别、分析时间（标题占1列，内容占3列）
                ["患者性别", sample.sample_info.patient_gender or "", 
                 "分析时间", sample.receive_time.strftime("%Y-%m-%d %H:%M:%S") if sample.receive_time else "未知", "", ""]
            ]
            
            # 创建头部表格样式
            header_style = TableStyle([
                # 设置标签列（第0、2、4列）的背景色为浅灰色
                ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),  # 第0列
                ('BACKGROUND', (2, 0), (2, -1), colors.lightgrey),  # 第2列  
                ('BACKGROUND', (4, 0), (4, -1), colors.lightgrey),  # 第4列
                
                # 设置整个表格的文字颜色为黑色
                ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
                
                # 设置整个表格左对齐
                ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                
                # 设置整个表格使用中文字体
                ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
                
                # 设置整个表格字体大小为10pt
                ('FONTSIZE', (0, 0), (-1, -1), 10),
                
                # 设置上下内边距为8pt
                ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
                ('TOPPADDING', (0, 0), (-1, -1), 8),
                
                # 设置内容列（第1、3、5列）的背景色为白色
                ('BACKGROUND', (1, 0), (1, -1), colors.white),  # 第1列
                ('BACKGROUND', (3, 0), (3, -1), colors.white),  # 第3列
                ('BACKGROUND', (5, 0), (5, -1), colors.white),  # 第5列
                
                # 添加黑色网格线
                ('GRID', (0, 0), (-1, -1), 1, colors.black),
                
                # 设置垂直居中对齐
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),

                # 设置表格的第三行的3、4、5列合并且背景颜色为白色
                ('BACKGROUND', (3, 2), (5, 2), colors.white),
                ('SPAN', (3, 2), (5, 2)),
            ])
            
            header_table = Table(header_data, colWidths=[2.5*cm, 3*cm, 2.5*cm, 3*cm, 2.5*cm, 3*cm])
            header_table.setStyle(header_style)
            story.append(header_table)
            story.append(Spacer(1, 20))
            
            # 添加色谱图部分
            chart_style = ParagraphStyle(
                'ChartTitle',
                parent=styles['Normal'],
                fontSize=12,
                spaceAfter=10,
                alignment=TA_CENTER,
                fontName=self._get_safe_font()
            )
            chart_title = Paragraph("色谱图", chart_style)
            story.append(chart_title)
            
            # 检查是否有真实的色谱图
            if sample.image and sample.image.path and os.path.exists(sample.image.path):
                # 使用真实的色谱图
                try:
                    # 检查文件是否为图片格式
                    image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.tif']
                    file_ext = os.path.splitext(sample.image.path)[1].lower()
                    
                    if file_ext in image_extensions:
                        # 创建图片对象，设置合适的大小
                        img = Image(sample.image.path, width=12*cm, height=8*cm, kind='proportional')
                        story.append(img)
                        logger.info(f"成功添加色谱图: {sample.image.path}")
                    else:
                        logger.warning(f"文件不是图片格式: {sample.image.path}")
                        # 如果不是图片格式，显示图片信息表格
                        self._add_image_info_table(story, sample)
                except Exception as e:
                    logger.warning(f"添加色谱图失败: {e}")
                    # 如果图片加载失败，显示图片信息表格
                    self._add_image_info_table(story, sample)
            elif sample.image and sample.image.filename:
                # 有图片信息但没有文件路径，显示图片信息
                self._add_image_info_table(story, sample)
            else:
                # 没有图片信息，显示模拟数据表格
                self._add_simulation_chart_table(story)
            story.append(Spacer(1, 20))
            
            # 添加检测结果表格
            results_title_style = ParagraphStyle(
                'ResultsTitle',
                parent=styles['Heading2'],
                fontSize=12,
                spaceAfter=10,
                alignment=TA_CENTER,
                fontName=self._get_safe_font()
            )
            results_title = Paragraph("检测结果", results_title_style)
            story.append(results_title)
            
            # 创建检测结果表格
            results_data = [
                ["检测项", "检测值", "单位", "出峰时间", "峰面积"]
            ]
            
            # 添加检测项目数据
            test_items = [
                ('HbA1a', sample.results.HbA1a, '%', '12.30', '0.12'),
                ('HbA1b', sample.results.HbA1b, '%', '12.30', '0.12'),
                ('HbF', sample.results.HbF, '%', '12.30', '0.12'),
                ('LA1c', sample.results.LA1c, '%', '12.30', '0.12'),
                ('HbA1c', sample.results.HbA1c, '%', '12.30', '0.12'),
                ('HbA0', sample.results.HbA0, '%', '12.30', '0.12'),
                ('eAG', sample.results.eAG, 'mg/dL', '12.30', '0.12'),
                ('A2', sample.results.A2, '%', '12.30', '0.12'),
                ('HbE', sample.results.HbE, '%', '12.30', '0.12'),
                ('HbD', sample.results.HbD, '%', '12.30', '0.12')
            ]
            
            for name, value, unit, peak_time, peak_area in test_items:
                if value is not None:
                    results_data.append([name, str(value), unit, peak_time, peak_area])
            
            # 创建结果表格样式
            results_table_style = TableStyle([
                ('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey),  # 表头背景
                ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
                ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
                ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
                ('FONTSIZE', (0, 0), (-1, -1), 9),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
                ('TOPPADDING', (0, 0), (-1, -1), 6),
                ('GRID', (0, 0), (-1, -1), 1, colors.black),
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                ('FONTNAME', (0, 0), (-1, 0), self._get_safe_font()),  # 表头字体
                ('FONTSIZE', (0, 0), (-1, 0), 10),  # 表头字号
            ])
            
            results_table = Table(results_data, colWidths=[3*cm, 3*cm, 2*cm, 3*cm, 3*cm])
            results_table.setStyle(results_table_style)
            story.append(results_table)
            
            # 生成PDF
            doc.build(story)
            return True
            
        except Exception as e:
            logger.error(f"生成样本PDF失败: {e}")
            return False
    
    def _add_image_info_table(self, story, sample: Sample):
        """添加图片信息表格"""
        # 创建图片信息表格
        image_data = [
            ["图片名称", sample.image.filename or "未知"],
            ["图片大小", f"{sample.image.size} bytes" if sample.image.size else "未知"],
            ["图片路径", sample.image.path or "未知"],
            ["保存状态", "已保存" if sample.image.saved else "未保存"]
        ]
        
        # 创建表格样式
        table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 9),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('TOPPADDING', (0, 0), (-1, -1), 6),
            ('BACKGROUND', (1, 0), (1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ])
        
        table = Table(image_data, colWidths=[3*cm, 8*cm])
        table.setStyle(table_style)
        story.append(table)
    
    def _add_simulation_chart_table(self, story):
        """添加模拟色谱图数据表格"""
        # 创建色谱图模拟数据表格
        chart_data = [
            ["时间(s)", "0", "10", "20", "30", "40", "50", "60", "70", "80"],
            ["信号值", "9.774", "9.780", "9.786", "9.792", "9.798", "9.804", "9.810", "9.816", "9.822"]
        ]
        
        chart_table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 9),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('TOPPADDING', (0, 0), (-1, -1), 6),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ])
        
        chart_table = Table(chart_data, colWidths=[2*cm] + [1.2*cm] * 9)
        chart_table.setStyle(chart_table_style)
        story.append(chart_table)
    
    def _create_basic_info_section(self, sample: Sample, styles) -> Paragraph:
        """创建基本信息部分"""
        # 基本信息表格
        basic_data = [
            ["患者姓名", sample.sample_info.patient_name or "未知患者"],
            ["患者年龄", str(sample.sample_info.patient_age) if sample.sample_info.patient_age else "未知"],
            ["患者性别", sample.sample_info.patient_gender or "未知"],
            ["样本位置", sample.sample_info.position or "未知"],
            ["样本类型", sample.sample_info.sample_type_name or "未知"],
            ["分析时间", sample.receive_time.strftime("%Y-%m-%d %H:%M:%S") if sample.receive_time else "未知"],
            ["接收时间", sample.created_time.strftime("%Y-%m-%d %H:%M:%S") if sample.created_time else "未知"],
            ["状态", sample.status.value if hasattr(sample.status, 'value') else str(sample.status)]
        ]
        
        # 创建表格样式
        table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (0, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('BACKGROUND', (1, 0), (1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ])
        
        table = Table(basic_data, colWidths=[3*cm, 8*cm])
        table.setStyle(table_style)
        
        # 包装在段落中
        section_style = ParagraphStyle(
            'SectionTitle',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=10,
            textColor=colors.darkblue
        )
        
        section_title = Paragraph("基本信息", section_style)
        
        # 返回组合内容
        from reportlab.platypus import KeepTogether
        return KeepTogether([section_title, table])
    
    def _create_instrument_info_section(self, sample: Sample, styles) -> Paragraph:
        """创建仪器信息部分"""
        # 仪器信息表格
        instrument_data = [
            ["仪器型号", sample.machine_model or "未知"],
            ["仪器编号", sample.machine_id or "未知"],
            ["分析模式", sample.analysis_mode or "未知"],
            ["协议类型", sample.protocol or "未知"]
        ]
        
        # 创建表格样式
        table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (0, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('BACKGROUND', (1, 0), (1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ])
        
        table = Table(instrument_data, colWidths=[3*cm, 8*cm])
        table.setStyle(table_style)
        
        # 包装在段落中
        section_style = ParagraphStyle(
            'SectionTitle',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=10,
            textColor=colors.darkblue
        )
        
        section_title = Paragraph("仪器信息", section_style)
        
        # 返回组合内容
        from reportlab.platypus import KeepTogether
        return KeepTogether([section_title, table])
    
    def _create_results_section(self, sample: Sample, styles) -> Paragraph:
        """创建检测结果部分"""
        # 百分比结果表格
        results_data = []
        
        # 基础检测项目
        basic_items = [
            ('HbA1a', sample.results.HbA1a),
            ('HbA1b', sample.results.HbA1b),
            ('HbF', sample.results.HbF),
            ('LA1c', sample.results.LA1c),
            ('HbA1c', sample.results.HbA1c),
            ('HbA0', sample.results.HbA0),
            ('eAG', sample.results.eAG)
        ]
        
        for name, value in basic_items:
            if value is not None:
                results_data.append([name, str(value), "%"])
        
        # 变异筛查项目
        variant_items = [
            ('A2', sample.results.A2),
            ('HbE', sample.results.HbE),
            ('HbD', sample.results.HbD),
            ('HbS', sample.results.HbS),
            ('HbC', sample.results.HbC),
            ('p3', sample.results.p3),
            ('v-win', sample.results.v_win)
        ]
        
        for name, value in variant_items:
            if value is not None:
                results_data.append([name, str(value), "%"])
        
        # TIME数据
        if sample.results.TIME and len(sample.results.TIME) > 0:
            time_values = [str(t) for t in sample.results.TIME if t is not None]
            if time_values:
                results_data.append(["TIME数据", ", ".join(time_values), "秒"])
        
        # AREA数据
        if sample.results.AREA and len(sample.results.AREA) > 0:
            area_values = [str(a) for a in sample.results.AREA if a is not None]
            if area_values:
                results_data.append(["AREA数据", ", ".join(area_values), ""])
        
        if not results_data:
            results_data = [["无检测结果", "", ""]]
        
        # 创建表格样式
        table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (0, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('BACKGROUND', (1, 0), (1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ])
        
        table = Table(results_data, colWidths=[3*cm, 6*cm, 2*cm])
        table.setStyle(table_style)
        
        # 包装在段落中
        section_style = ParagraphStyle(
            'SectionTitle',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=10,
            textColor=colors.darkblue
        )
        
        section_title = Paragraph("检测结果", section_style)
        
        # 返回组合内容
        from reportlab.platypus import KeepTogether
        return KeepTogether([section_title, table])
    
    def _create_image_section(self, sample: Sample, styles) -> Paragraph:
        """创建图片信息部分"""
        # 图片信息表格
        image_data = [
            ["图片名称", os.path.basename(sample.image.path) if sample.image.path else "未知"],
            ["图片大小", str(sample.image.size) if sample.image.size else "未知"],
            ["图片路径", sample.image.path or "未知"]
        ]
        
        # 创建表格样式
        table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (0, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('BACKGROUND', (1, 0), (1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ])
        
        table = Table(image_data, colWidths=[3*cm, 8*cm])
        table.setStyle(table_style)
        
        # 包装在段落中
        section_style = ParagraphStyle(
            'SectionTitle',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=10,
            textColor=colors.darkblue
        )
        
        section_title = Paragraph("图片信息", section_style)
        
        # 返回组合内容
        from reportlab.platypus import KeepTogether
        return KeepTogether([section_title, table])
    
    def _create_report_info_section(self, sample: Sample, styles) -> Paragraph:
        """创建报告信息部分"""
        # 报告信息表格
        report_data = [
            ["样本编号", sample.sample_info.sample_number or "未知"],
            ["报告ID", sample.sample_info.report_id or "未知"],
            ["生成时间", datetime.now().strftime("%Y-%m-%d %H:%M:%S")],
            ["报告状态", "已完成"]
        ]
        
        # 创建表格样式
        table_style = TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
            ('TEXTCOLOR', (0, 0), (0, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), self._get_safe_font()),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('BACKGROUND', (1, 0), (1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ])
        
        table = Table(report_data, colWidths=[3*cm, 8*cm])
        table.setStyle(table_style)
        
        # 包装在段落中
        section_style = ParagraphStyle(
            'SectionTitle',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=10,
            textColor=colors.darkblue
        )
        
        section_title = Paragraph("报告信息", section_style)
        
        # 返回组合内容
        from reportlab.platypus import KeepTogether
        return KeepTogether([section_title, table])
    
    def _add_excel_header(self, ws: Worksheet, sample_count: int):
        """添加Excel文件头部信息"""
        # 医院信息
        ws['A1'] = f"医院名称: {self.hospital_name}"
        ws['A2'] = f"导出时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
        ws['A3'] = f"样本总数: {sample_count}"
        
        # 设置标题样式
        title_font = Font(name='微软雅黑', size=12, bold=True)
        for cell in ['A1', 'A2', 'A3']:
            ws[cell].font = title_font
        
        # 空行
        ws['A5'] = ""
    
    def _add_sample_data(self, ws: Worksheet, samples: List[Sample], include_all_data: bool):
        """添加样本数据到Excel"""
        # 定义列标题 - 与主窗口表格保持一致
        if include_all_data:
            headers = [
                "序号", "样本编号", "患者姓名", "年龄", "性别", "仪器型号", "仪器编号", 
                "位置", "设备分析时间", "接收时间", "状态", "百分比结果", "TIME数据", "AREA数据", 
                "分析模式", "协议类型", "HbA1c", "LA1c", "HbA0", "eAG", "A2", "HbE", "HbD", "HbS", "HbC", "p3", "v-win"
            ]
        else:
            headers = [
                "序号", "样本编号", "患者姓名", "年龄", "性别", "仪器型号", "仪器编号", 
                "位置", "设备分析时间", "接收时间", "状态", "HbA1c", "LA1c", "HbA0", "eAG"
            ]
        
        # 添加表头
        for col, header in enumerate(headers, 1):
            cell = ws.cell(row=6, column=col, value=header)
            cell.font = Font(name='微软雅黑', size=10, bold=True)
            cell.fill = PatternFill(start_color="CCCCCC", end_color="CCCCCC", fill_type="solid")
            cell.alignment = Alignment(horizontal="center", vertical="center")
        
        # 添加数据行
        for row_idx, sample in enumerate(samples, 7):
            try:
                # 基本信息
                ws.cell(row=row_idx, column=1, value=row_idx - 6)  # 序号
                ws.cell(row=row_idx, column=2, value=sample.sample_info.sample_number)
                ws.cell(row=row_idx, column=3, value=sample.sample_info.patient_name)
                ws.cell(row=row_idx, column=4, value=sample.sample_info.patient_age)
                ws.cell(row=row_idx, column=5, value=sample.sample_info.patient_gender)
                ws.cell(row=row_idx, column=6, value=sample.machine_model)
                ws.cell(row=row_idx, column=7, value=sample.machine_id)
                ws.cell(row=row_idx, column=8, value=sample.sample_info.position)
                ws.cell(row=row_idx, column=9, value=sample.receive_time.strftime("%Y-%m-%d %H:%M:%S"))  # 设备分析时间
                ws.cell(row=row_idx, column=10, value=sample.created_time.strftime("%Y-%m-%d %H:%M:%S"))  # 接收时间
                
                # 状态字段处理
                if hasattr(sample.status, 'value'):
                    status_value = sample.status.value
                else:
                    status_value = str(sample.status)
                ws.cell(row=row_idx, column=11, value=status_value)
                
                if include_all_data:
                    # 百分比结果列 - 显示全部检测结果
                    percentage_results = f"HbA1a:{sample.results.HbA1a}, HbA1b:{sample.results.HbA1b}, HbF:{sample.results.HbF}, LA1c:{sample.results.LA1c}, HbA1c:{sample.results.HbA1c}, HbA0:{sample.results.HbA0}, eAG:{sample.results.eAG}, A2:{sample.results.A2}, HbE:{sample.results.HbE}, HbD:{sample.results.HbD}, HbS:{sample.results.HbS}, HbC:{sample.results.HbC}, p3:{sample.results.p3}, v-win:{sample.results.v_win}"
                    ws.cell(row=row_idx, column=12, value=percentage_results)
                    
                    # TIME数据
                    time_data = self._format_array_data(sample.results.TIME)
                    ws.cell(row=row_idx, column=13, value=time_data)
                    
                    # AREA数据
                    area_data = self._format_array_data(sample.results.AREA)
                    ws.cell(row=row_idx, column=14, value=area_data)
                    
                    # 分析模式
                    ws.cell(row=row_idx, column=15, value=sample.analysis_mode)
                    
                    # 协议类型
                    ws.cell(row=row_idx, column=16, value=sample.protocol)
                    
                    # 详细检测结果
                    ws.cell(row=row_idx, column=17, value=sample.results.HbA1c)
                    ws.cell(row=row_idx, column=18, value=sample.results.LA1c)
                    ws.cell(row=row_idx, column=19, value=sample.results.HbA0)
                    ws.cell(row=row_idx, column=20, value=sample.results.eAG)
                    ws.cell(row=row_idx, column=21, value=sample.results.A2)
                    ws.cell(row=row_idx, column=22, value=sample.results.HbE)
                    ws.cell(row=row_idx, column=23, value=sample.results.HbD)
                    ws.cell(row=row_idx, column=24, value=sample.results.HbS)
                    ws.cell(row=row_idx, column=25, value=sample.results.HbC)
                    ws.cell(row=row_idx, column=26, value=sample.results.p3)
                    ws.cell(row=row_idx, column=27, value=sample.results.v_win)
                else:
                    # 简化模式 - 只显示主要检测结果
                    ws.cell(row=row_idx, column=12, value=sample.results.HbA1c)
                    ws.cell(row=row_idx, column=13, value=sample.results.LA1c)
                    ws.cell(row=row_idx, column=14, value=sample.results.HbA0)
                    ws.cell(row=row_idx, column=15, value=sample.results.eAG)
                
                # 设置行样式
                self._set_row_style(ws, row_idx, len(headers))
                
            except Exception as e:
                logger.error(f"处理样本数据失败 (行 {row_idx}): {e}")
                continue
    
    def _format_array_data(self, data_array) -> str:
        """格式化数组数据为字符串"""
        if not data_array:
            return ""
        
        try:
            # 过滤掉None和空值
            valid_data = [str(item) for item in data_array if item is not None]
            return ", ".join(valid_data)
        except Exception:
            return ""
    
    def _set_row_style(self, ws: Worksheet, row: int, col_count: int):
        """设置行样式"""
        try:
            # 设置边框
            thin_border = Border(
                left=Side(style='thin'),
                right=Side(style='thin'),
                top=Side(style='thin'),
                bottom=Side(style='thin')
            )
            
            for col in range(1, col_count + 1):
                cell = ws.cell(row=row, column=col)
                cell.border = thin_border
                cell.alignment = Alignment(horizontal="center", vertical="center")
                
                # 设置字体
                cell.font = Font(name='微软雅黑', size=9)
        except Exception as e:
            logger.error(f"设置行样式失败: {e}")
    
    def _set_column_widths(self, ws: Worksheet, include_all_data: bool):
        """设置列宽"""
        try:
            if include_all_data:
                column_widths = [
                    6, 12, 10, 6, 6, 12, 12, 10, 18, 18, 8, 50, 30, 30, 12, 12,
                    8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 8
                ]
            else:
                column_widths = [6, 12, 10, 6, 6, 12, 12, 10, 18, 18, 8, 8, 8, 8, 8]
            
            for col, width in enumerate(column_widths, 1):
                ws.column_dimensions[openpyxl.utils.get_column_letter(col)].width = width
                
        except Exception as e:
            logger.error(f"设置列宽失败: {e}")
    
    def export_filtered_samples_to_excel(self, samples: List[Sample], file_path: str, 
                                       filters: Dict[str, Any] = None) -> bool:
        """导出过滤后的样本数据到Excel"""
        try:
            if not samples:
                logger.warning("没有样本数据可导出")
                return False
            
            # 创建工作簿
            wb = openpyxl.Workbook()
            ws = wb.active
            ws.title = "样本数据"
            
            # 设置标题（包含过滤条件）
            self._add_filtered_excel_header(ws, len(samples), filters)
            
            # 添加数据
            self._add_sample_data(ws, samples, include_all_data=True)
            
            # 设置列宽
            self._set_column_widths(ws, include_all_data=True)
            
            # 保存文件
            wb.save(file_path)
            logger.info(f"过滤样本Excel文件导出成功: {file_path}")
            return True
            
        except Exception as e:
            logger.error(f"导出过滤样本Excel文件失败: {e}")
            return False
    
    def _add_filtered_excel_header(self, ws: Worksheet, sample_count: int, filters: Dict[str, Any] = None):
        """添加带过滤条件的Excel文件头部信息"""
        # 医院信息
        ws['A1'] = f"医院名称: {self.hospital_name}"
        ws['A2'] = f"导出时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
        ws['A3'] = f"样本总数: {sample_count}"
        
        # 过滤条件
        if filters:
            filter_text = "过滤条件: "
            filter_parts = []
            for key, value in filters.items():
                if value:
                    filter_parts.append(f"{key}={value}")
            if filter_parts:
                filter_text += ", ".join(filter_parts)
                ws['A4'] = filter_text
        
        # 设置标题样式
        title_font = Font(name='微软雅黑', size=12, bold=True)
        for cell in ['A1', 'A2', 'A3', 'A4']:
            if ws[cell].value:
                ws[cell].font = title_font
        
        # 空行
        ws['A6'] = ""
    
    def get_export_summary(self, samples: List[Sample]) -> Dict[str, Any]:
        """获取导出摘要信息"""
        try:
            if not samples:
                return {"total": 0, "status_count": {}, "date_range": None}
            
            # 状态统计
            status_count = {}
            for sample in samples:
                if hasattr(sample.status, 'value'):
                    status = sample.status.value
                else:
                    status = str(sample.status)
                status_count[status] = status_count.get(status, 0) + 1
            
            # 时间范围
            dates = [sample.receive_time for sample in samples if sample.receive_time]
            if dates:
                min_date = min(dates)
                max_date = max(dates)
                date_range = f"{min_date.strftime('%Y-%m-%d')} 至 {max_date.strftime('%Y-%m-%d')}"
            else:
                date_range = None
            
            return {
                "total": len(samples),
                "status_count": status_count,
                "date_range": date_range,
                "export_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
            
        except Exception as e:
            logger.error(f"获取导出摘要失败: {e}")
            return {"total": 0, "status_count": {}, "date_range": None}
